home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1996 #15 / Monster Media Number 15 (Monster Media)(July 1996).ISO / math / hugemath.zip / HUGEMATH.C < prev    next >
C/C++ Source or Header  |  1996-04-06  |  35KB  |  1,412 lines

  1. /*
  2.    HUGEMATH :
  3.    This program is basically a calculator which works with integers
  4.    These can be more or less as large as you want. The exe file supplied
  5.    has been compiled to accept integers up to about 500 digits each.
  6.    Some of the code may be difficult to read because it has been optimised
  7.    as far as possible. Many primality tests have also been implemented.
  8.    See the doc file for a description of usage.
  9.  
  10.    This program was written by Paul Young, using Turbo C++.
  11.    I accept no responsibility for use or misuse of this program in any way.
  12.    This program is Public Domain.
  13.    It may be copied freely provided this notice is included.
  14.    This program may be used as a base or included in other programs
  15.    however these programs must also be Public Domain and no monetary gain
  16.    should be made from these. Help support Public Domain programming.
  17.    P Young, 101716.3323@compuserve.com
  18. */
  19.  
  20. /*
  21.    This program should be compiled with the smallest possible memory
  22.    model. This is so that it runs at the fastest speed possible, because
  23.    near pointers will be used. Unless anyone has a better idea.
  24.    Unfortunately it limits the size.
  25. */
  26.  
  27. #include <conio.h>;
  28. #include <stdio.h>;
  29. #include <stdlib.h>;
  30. #include <string.h>;
  31. #include <time.h>;
  32.  
  33. #define TRUE 1
  34. #define FALSE 0
  35.  
  36. #define NIL 0
  37. #define REG 1
  38. #define CVALUE 2
  39. #define NUM 3
  40. #define TVAL 4
  41. #define FVAL 5
  42. #define QUIT 6
  43.  
  44. #define MAXLEN 120
  45.  
  46. #define NUM_SIEVEVALUES 20
  47.  
  48. /*
  49.    global variables
  50.    the regA,etc are registers for the calculator
  51.    they consist of reg[0] which indicates the length of data
  52.    and reg[1]..reg[length] which is lsb..msb of number.
  53.    Holding the length like this makes the program generally more
  54.    efficient. Fixed length numbers of 500 digits are s-l-o-w.
  55. */
  56.  
  57. unsigned int regA[2*MAXLEN+1];
  58. unsigned int regB[2*MAXLEN+1];
  59. unsigned int regC[2*MAXLEN+1];
  60. unsigned int regD[2*MAXLEN+1];
  61. typedef unsigned char bool;
  62. unsigned int primes[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,
  63.                67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,
  64.                139,149,151,157,163,167,173,179,181,191,193,197,199,
  65.                211,223,227,229,233,239,241,251,0};
  66. unsigned int sievevalue[NUM_SIEVEVALUES]={256,243,125,49,121,169,17,19,23,
  67.                       29,31,37,41,43,47,53,59,61,67,71};
  68. unsigned int sieves[256*NUM_SIEVEVALUES];
  69. unsigned int modtable[NUM_SIEVEVALUES];
  70.  
  71. /*
  72.    prototypes for functions
  73. */
  74.  
  75. void hugeadd(unsigned int *reg1,unsigned int *reg2,bool checkoverflow);
  76. void hugermul(unsigned int *reg1,unsigned int *reg2,bool checkoverflow);
  77. void hugerdiv(unsigned int *reg1,unsigned int *reg2,bool divmod);
  78. void hugepri(unsigned int *reg1,bool suppress);
  79. void hugemod(unsigned int *reg1,unsigned int num,unsigned int *carry);
  80. void hugeinc(unsigned int *reg1,bool checkoverflow);
  81. void hugedec(unsigned int *reg1);
  82. void hugeequ(unsigned int *reg1,unsigned int *reg2);
  83. void hugemul2(unsigned int *reg1,bool checkoverflow);
  84. void hugediv2(unsigned int *reg1,unsigned int *carry);
  85. void hugersub(unsigned int *reg1,unsigned int *reg2);
  86. void hugetdiv(unsigned int *reg1,int kvalue);
  87. void repunit(unsigned int *reg1,unsigned int num);
  88. void mersenne(unsigned int *reg1,unsigned int num);
  89. void fibonacci(unsigned int *reg1,unsigned int num);
  90. void factorise(unsigned int *reg1);
  91. void hugeinp(unsigned int *reg1,char *buffer);
  92. void hugeswap(unsigned int *reg1,unsigned int *reg2);
  93. void hugepriregs(void);
  94. void hugegcd(unsigned int *reg1,unsigned int *reg2);
  95. void mprime(unsigned int *reg1,unsigned int num);
  96. void hugeroot(unsigned int *reg1,unsigned int *reg2);
  97. void psptest(unsigned int *reg1,unsigned int num);
  98. void pollard(unsigned int *reg1,unsigned int num);
  99. void sequence(unsigned int *reg1,unsigned int num);
  100. void montecarlo(unsigned int *reg1,unsigned int num);
  101. void autopsptest(unsigned int *reg1,unsigned int num);
  102. void proveprime(unsigned int *reg1,unsigned int *reg2);
  103. void findwitness(unsigned int *reg1,unsigned int *reg2);
  104. void witness(unsigned int *reg1,unsigned int *reg2,unsigned int num);
  105. void factorial(unsigned int *reg1,unsigned int num);
  106. void power2(unsigned int *reg1,unsigned int num);
  107. void pown(unsigned int *reg1,unsigned int num);
  108. void fermatsieve(unsigned int *reg1);
  109.  
  110. /*
  111.    Here is the table of options available
  112. */
  113.  
  114. struct
  115. { char *cmd;
  116.   void (*fn)();
  117.   int arg1,
  118.       arg2,
  119.       arg3;
  120. } comtable[]={ {"add",hugeadd,REG,CVALUE,TVAL},
  121.            {"div",hugerdiv,REG,CVALUE,TVAL},
  122.            {"mul",hugermul,REG,CVALUE,TVAL},
  123.            {"sub",hugersub,REG,CVALUE,NIL},
  124.            {"mod",hugerdiv,REG,CVALUE,FVAL},
  125.            {"priall",hugepriregs,NIL,NIL,NIL},
  126.            {"pri",hugepri,REG,NIL,FVAL},
  127.            {"inc",hugeinc,REG,NIL,TVAL},
  128.            {"dec",hugedec,REG,NIL,NIL},
  129.            {"equ",hugeequ,REG,CVALUE,NIL},
  130.            {"swap",hugeswap,REG,CVALUE,NIL},
  131.            {"mul2",hugemul2,REG,NIL,TVAL},
  132.            {"div2",hugediv2,REG,NIL,NIL},
  133.            {"rep",repunit,REG,NUM,NIL},
  134.            {"fib",fibonacci,REG,NUM,NIL},
  135.            {"smallfac",factorise,REG,NIL,NIL},
  136.            {"mer",mersenne,REG,NUM,NIL},
  137.            {"tdiv",hugetdiv,REG,NUM,NIL},
  138.            {"gcd",hugegcd,REG,CVALUE,NIL},
  139.            {"mprime",mprime,REG,NUM,NIL},
  140.            {"root",hugeroot,REG,CVALUE,NIL},
  141.            {"psp",psptest,REG,NUM,NIL},
  142.            {"pollard",pollard,REG,NUM,NIL},
  143.            {"autopsp",autopsptest,REG,NUM,NIL},
  144.            {"monte",montecarlo,REG,NUM,NIL},
  145.            {"sequence",sequence,REG,NUM,NIL},
  146.            {"findwitness",findwitness,REG,CVALUE,NIL},
  147.            {"proveprime",proveprime,REG,CVALUE,NIL},
  148.            {"2pow",power2,REG,NUM,NIL},
  149.            {"npow",pown,REG,NUM,NIL},
  150.            {"factorial",factorial,REG,NUM,NIL},
  151.            {"fermat",fermatsieve,REG,NIL,NIL},
  152.            {"quit",NULL,QUIT,NIL,NIL},
  153.            {NULL,NULL,NIL,NIL,NIL}
  154.          };
  155.  
  156. /*
  157.    sets all registers to zero
  158. */
  159.  
  160. void init(void)
  161. { regA[0]=0;
  162.   regB[0]=0;
  163.   regC[0]=0;
  164.   regD[0]=0;
  165. }
  166.  
  167. /*
  168.    exits program on overflow.
  169.    you may want to change this to continue
  170. */
  171.  
  172. void overflow(int num)
  173. { printf("Overflow occurred at %d\n\r",num);
  174.   exit(1);
  175. }
  176.  
  177. /*
  178.    adds two of the numbers together
  179.    this is complicated due to possible differing lengths of numbers
  180. */
  181.  
  182. void hugeadd(unsigned int *reg1,unsigned int *reg2,bool checkoverflow)
  183. { int len1=reg1[0],
  184.       len2=reg2[0];
  185.   register count;
  186.   unsigned long temp=0;
  187.   if (len2>len1)       /* pad shortest with zeroes */
  188.   { for (count=len1+1;count<=len2;count++) reg1[count]=0;
  189.     len1=len2;
  190.   }
  191.   else if (len2<len1) for (count=len2+1;count<=len1;count++) reg2[count]=0;
  192.   count=1;
  193.   while (len1--)       /* now add them */
  194.   { temp+=(long)reg1[count]+reg2[count];
  195.     reg1[count++]=temp;
  196.     temp>>=16;
  197.   }
  198.   if (!temp) reg1[0]=--count;      /* and check length of result */
  199.   else if ((checkoverflow)&&(count>MAXLEN)) overflow(1);
  200.        else reg1[reg1[0]=count]=temp;
  201. }
  202.  
  203. /*
  204.    simple division routine for reg by int
  205. */
  206.  
  207. void hugediv(unsigned int *reg1,unsigned int num,unsigned int *carry)
  208. { register len1=reg1[0];
  209.   unsigned long temp=0;
  210.   *carry=0;
  211.   if (!num) { overflow(2);
  212.           return;
  213.         }
  214.   while (len1)
  215.   { temp=reg1[len1]+(((long)*carry)<<16);
  216.     *carry=temp%num;
  217.     reg1[len1--]=temp/num;
  218.   }
  219.   if (!reg1[reg1[0]]) reg1[0]--;
  220. }
  221.  
  222. /*
  223.    simple multiply for reg by int
  224.    the checkoverflow variable is normally true however some
  225.    routines use intermediate values which may be larger than
  226.    the normal maximum. These have large temporary registers
  227.    and overflow will not occur
  228. */
  229.  
  230. void hugemul(unsigned int *reg1,unsigned int num,bool checkoverflow)
  231. { int len1=reg1[0],
  232.       count=1;
  233.   unsigned long temp=0;
  234.   while (len1--)
  235.   { temp+=(long)num*reg1[count];
  236.     reg1[count++]=temp;
  237.     temp>>=16;
  238.   }
  239.   if (!temp) return;
  240.   if ((checkoverflow)&&(count>MAXLEN)) overflow(3);
  241.   reg1[reg1[0]=count]=temp;
  242. }
  243.  
  244. /*
  245.    this prints a reg to the screen
  246. */
  247.  
  248. void hugepri(unsigned int *reg1,bool suppress)
  249. { unsigned int reg2[MAXLEN+1],
  250.            ch;
  251.   char buffer[5*MAXLEN+2];
  252.   register count;
  253.   for (count=0;count<=reg1[0];count++) reg2[count]=reg1[count];
  254.   if (!reg1[0]) { printf("0\n\r");
  255.           return;
  256.         }
  257.   count=0;
  258.   while (reg2[0])
  259.   { hugediv(reg2,10,&ch);
  260.     buffer[count++]=ch+'0';
  261.   }
  262.   while (count) printf("%c",buffer[--count]);
  263.   if(!suppress)printf("\n\r");
  264. }
  265.  
  266. /*
  267.    simple mod routine for reg mod int
  268. */
  269.  
  270. void hugemod(unsigned int *reg1,unsigned int num,unsigned int *carry)
  271. { register len1=reg1[0];
  272.   unsigned long temp=0;
  273.   *carry=0;
  274.   if (!num) { overflow(4);
  275.           return;
  276.         }
  277.   while (len1)
  278.   { temp=reg1[len1--]+(((long)*carry)<<16);
  279.     *carry=temp%num;
  280.   }
  281. }
  282.  
  283. /*
  284.    increments reg. Complicated again due to need to check for
  285.    length increase in reg.
  286. */
  287.  
  288. void hugeinc(unsigned int *reg1,bool checkoverflow)
  289. { int len1=reg1[0],
  290.       carry=1,
  291.       temp=1;
  292.   while (len1--)
  293.   { reg1[temp]+=carry;
  294.     if (reg1[temp++]){ len1=0;
  295.                carry=0;
  296.              }
  297.   }
  298.   if (carry) if ((checkoverflow)&&(temp>MAXLEN)) overflow(5);
  299.          else reg1[reg1[0]=temp]=1;
  300. }
  301.  
  302. /*
  303.    heres the corresponding decrement
  304. */
  305.  
  306. void hugedec(unsigned int *reg1)
  307. { int len1=reg1[0],
  308.       carry=1,
  309.       temp=1;
  310.   if (!len1) { overflow(6);
  311.            return;
  312.          }
  313.   while ((len1--)&&(carry))
  314.   { reg1[temp]-=carry;
  315.     if (reg1[temp++]+1) carry=0;
  316.   }
  317.   if (!reg1[reg1[0]]) reg1[0]--;
  318. }
  319.  
  320. /*
  321.    fast equal
  322. */
  323.  
  324. void hugeequ(unsigned int *reg1,unsigned int *reg2)
  325. { memmove(reg1,reg2,(reg2[0]+1)*sizeof(unsigned int));
  326. }
  327.  
  328. /*
  329.    fast multiply by two using shifting
  330. */
  331.  
  332. void hugemul2(unsigned int *reg1,bool checkoverflow)
  333. { int len1=reg1[0];
  334.   register count=1;
  335.   unsigned long temp=0;
  336.   while(len1--)
  337.   { temp+=(((long)reg1[count])<<1);
  338.     reg1[count++]=temp;
  339.     temp>>=16;
  340.   }
  341.   if(!temp)return;
  342.   if((checkoverflow)&&(count>MAXLEN))overflow(7);
  343.   reg1[reg1[0]=count]=1;
  344. }
  345.  
  346. /*
  347.    fast div by two using shifting
  348. */
  349.  
  350. void hugediv2(unsigned int *reg1,unsigned int *carry)
  351. { register len1=reg1[0];
  352.   unsigned long temp=0;
  353.   *carry=0;
  354.   while(len1)
  355.   { temp=reg1[len1]+(((long)*carry)<<16);
  356.     *carry=temp&1;
  357.     reg1[len1--]=temp>>1;
  358.   }
  359.   len1=reg1[0];
  360.   if(!len1)return;
  361.   if(!reg1[len1])reg1[0]--;
  362. }
  363.  
  364. /*
  365.    multiplies two numbers together
  366.    each of large size
  367.    fairly simple stuff
  368. */
  369.  
  370. void hugermul(unsigned int *reg1,unsigned int *reg2,bool checkoverflow)
  371. { unsigned int result[2*MAXLEN+1];
  372.   int len2=reg2[0],
  373.       mult;
  374.   register count;
  375.   if((!len2)||(!reg1[0])) { reg1[0]=0;
  376.                 return;
  377.               }
  378.   result[0]=0;
  379.   while(len2)
  380.   { mult=reg2[len2--];
  381.     for(count=0;count<16;count++)
  382.     { hugemul2(result,checkoverflow);
  383.       if(mult&32768)hugeadd(result,reg1,checkoverflow);
  384.       mult<<=1;
  385.     }
  386.   }
  387.   hugeequ(reg1,result);
  388. }
  389.  
  390. /*
  391.    subtracts two large numbers
  392.    careful with result length.
  393. */
  394.  
  395. void hugersub(unsigned int *reg1,unsigned int *reg2)
  396. { int len1=reg1[0],
  397.       len2=reg2[0],
  398.       carry=0;
  399.   register count=1;
  400.   unsigned long temp=0;
  401.   if(len2>len1){ overflow(8);
  402.          return;
  403.            }
  404.   while(len2--)
  405.   { temp=(long)reg1[count]-reg2[count]-carry;
  406.     reg1[count++]=temp;
  407.     carry=(temp>>16)&1;
  408.     len1--;
  409.   }
  410.   while((len1--)&&(carry)) if(reg1[count++]--)carry=0;
  411.   while((reg1[0])&&(!reg1[reg1[0]]))reg1[0]--;
  412.   if(carry)overflow(9);
  413. }
  414.  
  415. /*
  416.    adds int to reg the quick way
  417. */
  418.  
  419. void hugeaddnum(unsigned int *reg1,unsigned int value,bool checkoverflow)
  420. { unsigned int tmp[2*MAXLEN+1];
  421.   if(!value)return;
  422.   tmp[0]=1;
  423.   tmp[1]=value;
  424.   hugeadd(reg1,tmp,checkoverflow);
  425. }
  426.  
  427. /*
  428.    divides one reg by another
  429.    fairly quick
  430.    this seems to be the one most people avoid
  431.    fairly straightforward if you can think in binary
  432. */
  433.  
  434. void hugerdiv(unsigned int *reg1,unsigned int *reg2,bool divmod)
  435. { unsigned int result[2*MAXLEN+1],
  436.            carry;
  437.   int count=0;
  438.   register len1=reg1[0];
  439.   bool greater;
  440.   if(!reg2[0]){ overflow(10);
  441.         return;
  442.           }
  443.   while((reg2[0]<len1)||((reg2[0]==len1)&&(reg2[reg2[0]]<reg1[len1])))
  444.   { hugemul2(reg2,FALSE);
  445.     count++;
  446.   }
  447.   result[0]=0;
  448.   do
  449.   { if(reg1[0]>reg2[0])greater=TRUE;
  450.     else
  451.     if(reg2[0]>reg1[0])greater=FALSE;
  452.     else
  453.     { greater=TRUE;
  454.       len1=reg1[0];
  455.       do greater=!(reg1[len1]<reg2[len1--]);
  456.       while((greater)&&(reg1[len1+1]==reg2[len1+1])&&(len1));
  457.     }
  458.     if (greater) { hugersub(reg1,reg2);
  459.            hugeinc(result,FALSE);
  460.          }
  461.     if (count) { hugediv2(reg2,&carry);
  462.          hugemul2(result,FALSE);
  463.            }
  464.   } while(count--);
  465.   if (divmod) hugeequ(reg1,result);
  466. }
  467.  
  468. /*
  469.    used by trial division
  470. */
  471.  
  472. void hugecheckb(unsigned int *testval,unsigned int *reg1)
  473. { unsigned int modres[MAXLEN+1],
  474.            count=0,
  475.            carry;
  476.   int i=1;
  477.   bool fin;
  478.   while(primes[i])
  479.   { hugemod(testval,primes[i++],&carry);
  480.     if(!carry)return;
  481.   }
  482.   do
  483.   { hugeequ(modres,reg1);
  484.     hugerdiv(modres,testval,fin=FALSE);
  485.     if(!modres[0]) { hugerdiv(reg1,testval,fin=TRUE);
  486.              count++;
  487.            }
  488.   } while(fin);
  489.   if(count) { printf("Factor : ");
  490.           hugepri(testval,TRUE);
  491.           if(count>1)printf(" ^ %u",count);
  492.           printf("\n\r");
  493.         }
  494. }
  495.  
  496. /*
  497.    also used by trial division
  498.    tests numbers of the form
  499.    6n-1,6n+1
  500. */
  501.  
  502. void hugechecka(unsigned int *testval,unsigned int *reg1)
  503. { hugedec(testval);
  504.   hugecheckb(testval,reg1);
  505.   hugeaddnum(testval,2,TRUE);
  506.   hugecheckb(testval,reg1);
  507.   hugedec(testval);
  508. }
  509.  
  510. /*
  511.    heres the trial division
  512.    starts at 65536 - see factor which finds small factors quickly
  513.    use only if really stuck in factoring or you know a special
  514.    property - for example factors are of form 1024k+-1
  515. */
  516.  
  517. void hugetdiv(unsigned int *reg1,int kvalue)
  518. { unsigned int testval[MAXLEN+1],
  519.            squareval[MAXLEN+1],
  520.            calcval,
  521.            len1;
  522.   bool greater;
  523.   calcval=(int)((long)65536L/kvalue)*kvalue;
  524.   testval[0]=1;
  525.   testval[1]=calcval;
  526.   do
  527.   { hugeaddnum(testval,kvalue,TRUE);
  528.     hugechecka(testval,reg1);
  529.     hugeequ(squareval,testval);
  530.     hugermul(squareval,testval,TRUE);
  531.     if(kbhit()){ hugepri(testval,FALSE);
  532.          if(getch()=='e')return;
  533.            }
  534.     len1=squareval[0];
  535.     if(len1>reg1[0])greater=TRUE;
  536.     else if(len1<reg1[0])greater=FALSE;
  537.      else
  538.      { greater=TRUE;
  539.        do greater=!(squareval[len1]<reg1[len1--]);
  540.        while((greater)&&(squareval[len1+1]==reg1[len1+1])&&(len1));
  541.      }
  542.     if(greater) { printf("Factor : ");
  543.           hugepri(reg1,FALSE);
  544.           printf("Factored\n");
  545.         }
  546.   } while(!greater);
  547. }
  548.  
  549. /*
  550.    calculates repunit
  551. */
  552.  
  553. void repunit(unsigned int *reg1,unsigned int num)
  554. { reg1[0]=0;
  555.   while (num--)
  556.   { hugemul(reg1,10,TRUE);
  557.     hugeinc(reg1,TRUE);
  558.   }
  559. }
  560.  
  561. /*
  562.    calculates mersenne number
  563. */
  564.  
  565. void mersenne(unsigned int *reg1,unsigned int num)
  566. { reg1[0]=0;
  567.   while (num--)
  568.   { hugemul(reg1,2,TRUE);
  569.     hugeinc(reg1,TRUE);
  570.   }
  571. }
  572.  
  573. /*
  574.    calculates fibonacci number
  575. */
  576.  
  577. void fibonacci(unsigned int *reg1,unsigned int num)
  578. { unsigned int reg2[MAXLEN+1],
  579.            reg3[MAXLEN+1],
  580.            *r2,
  581.            *r3,
  582.            *temp;
  583.   reg2[0]=0;
  584.   r2=reg2;
  585.   reg3[0]=0;
  586.   r3=reg3;
  587.   hugeinc(reg3,TRUE);
  588.   while (num--)
  589.   { hugeadd(r2,r3,TRUE);
  590.     temp=r2;
  591.     r2=r3;
  592.     r3=temp;
  593.   }
  594.   hugeequ(reg1,r2);
  595. }
  596.  
  597. /*
  598.    check for small factor, quick
  599. */
  600.  
  601. bool factor(unsigned int *reg1,unsigned int trial)
  602. { unsigned int carry;
  603.   hugemod(reg1,trial,&carry);
  604.   if(!carry)
  605.   { hugediv(reg1,trial,&carry);
  606.     return TRUE;
  607.   }
  608.   return FALSE;
  609. }
  610.  
  611. /*
  612.    removes small factors
  613.    quick on a DX2 for very large numbers
  614. */
  615.  
  616. void factorise(unsigned int *reg1)
  617. { unsigned int trial=1,
  618.            count=0,
  619.            res;
  620.   bool prime;
  621.   if(!reg1[0])return;
  622.   while(factor(reg1,2))count++;
  623.   if(count){ printf("Factor : 2");
  624.          if(count>1)printf(" ^ %u ",count);
  625.          printf("\n");
  626.        }
  627.   do
  628.   { do
  629.     { trial+=2;
  630.       res=3;
  631.       prime=TRUE;
  632.       while((res*res<=trial)&&(prime))
  633.       { if(!(trial%res))prime=FALSE;
  634.     res+=2;
  635.       }
  636.     } while(!prime);
  637.     if(trial>1)
  638.     { count=0;
  639.       while(factor(reg1,trial))count++;
  640.       if(count){ printf("Factor : %u",trial);
  641.          if(count>1)printf(" ^ %u",count);
  642.          printf("\n");
  643.            }
  644.     }
  645.   } while(trial!=1);
  646. }
  647.  
  648. /*
  649.    converts buffer input to number for reg
  650. */
  651.  
  652. void hugeinp(unsigned int *reg1,char *buffer)
  653. { int count=0;
  654.   reg1[0]=0;
  655.   while(buffer[count])
  656.   { hugemul(reg1,10,TRUE);
  657.     hugeaddnum(reg1,buffer[count++]-'0',TRUE);
  658.   }
  659. }
  660.  
  661. /*
  662.    swaps two large numbers
  663. */
  664.  
  665. void hugeswap(unsigned int *reg1,unsigned int *reg2)
  666. { int t;
  667.   unsigned int tmp;
  668.   t=(reg1[0]>reg2[0]) ? reg1[0]:reg2[0];
  669.   while(t>=0)
  670.   { tmp=reg1[t];
  671.     reg1[t]=reg2[t];
  672.     reg2[t--]=tmp;
  673.   }
  674. }
  675.  
  676. /*
  677.    prints all regs to screen
  678. */
  679.  
  680. void hugepriregs(void)
  681. { printf("a = ");
  682.   hugepri(regA,FALSE);
  683.   printf("b = ");
  684.   hugepri(regB,FALSE);
  685.   printf("c = ");
  686.   hugepri(regC,FALSE);
  687.   printf("d = ");
  688.   hugepri(regD,FALSE);
  689. }
  690.  
  691. /*
  692.    calculates gcd of two regs
  693. */
  694.  
  695. void hugegcd(unsigned int *reg1,unsigned int *reg2)
  696. { unsigned int work1[MAXLEN+1];
  697.   hugeequ(work1,reg2);
  698.   do
  699.   { hugerdiv(reg1,work1,FALSE);
  700.     hugeswap(reg1,work1);
  701.   } while(work1[0]);
  702. }
  703.  
  704. /*
  705.    calculates mprime value (or prime fac)
  706.    ie 3*5*7*11*13*... up to num
  707. */
  708.  
  709. void mprime(unsigned int *reg1,unsigned int num)
  710. { unsigned int count=0;
  711.   reg1[0]=0;
  712.   hugeinc(reg1,TRUE);
  713.   while((primes[count]<=num)&&(primes[count]))
  714.     hugemul(reg1,primes[count++],TRUE);
  715. }
  716.  
  717. /*
  718.    squareroot - nice fast root extraction in binary
  719.    get the old schoolbooks out for this one
  720.    best to try it on pen and paper but it works.
  721. */
  722.  
  723. void hugeroot(unsigned int *reg1,unsigned int *reg2)
  724. { unsigned int quotient[MAXLEN+1];
  725.   unsigned int reg2byte,
  726.            bytecount,
  727.            lengthcount,
  728.            carry,
  729.            len1;
  730.   bool greater;
  731.   quotient[0]=reg1[0]=0;
  732.   lengthcount=reg2[0];
  733.   while(lengthcount)
  734.   { reg2byte=reg2[lengthcount--];
  735.     for(bytecount=0;bytecount<8;bytecount++)
  736.     { hugemul(quotient,4,TRUE);
  737.       hugeaddnum(quotient,reg2byte>>14,TRUE);
  738.       hugemul(reg1,4,TRUE);
  739.       if(quotient[0]>reg1[0])greater=TRUE;
  740.       else if(quotient[0]<reg1[0])greater=FALSE;
  741.       else { greater=FALSE;
  742.          len1=quotient[0];
  743.          do
  744.          { if(quotient[len1]>reg1[len1])greater=TRUE;
  745.          } while((quotient[len1]==reg1[len1])&&(len1--));
  746.        }
  747.       if(greater) { hugersub(quotient,reg1);
  748.             hugedec(quotient);
  749.             hugeaddnum(reg1,2,TRUE);
  750.           }
  751.       hugediv2(reg1,&carry);
  752.       reg2byte<<=2;
  753.     }
  754.   }
  755. }
  756.  
  757. /*
  758.    this is used in psptest,etc
  759.    it calculates reg1*reg2 mod reg3
  760.    this is what I meant earlier by large intermediate values
  761.    overflow will not occur but checking needs to be off
  762. */
  763.  
  764. void hugemulmod(unsigned int *reg1,unsigned int *reg2,unsigned int *reg3)
  765. { hugermul(reg1,reg2,FALSE);
  766.   hugerdiv(reg1,reg3,FALSE);
  767. }
  768.  
  769. /*
  770.    heres the pseudoprime test
  771.    see any modern number theory book
  772.    a pseudoprime is not necessarily prime
  773. */
  774.  
  775. void psptest(unsigned int *reg1,unsigned int num)
  776. { unsigned int result[2*MAXLEN+1],
  777.            len1,
  778.            reg1byte,
  779.            bytecount;
  780.   result[0]=result[1]=1;
  781.   len1=reg1[0];
  782.   while(len1)
  783.   { reg1byte=reg1[len1--];
  784.     for(bytecount=0;bytecount<16;bytecount++)
  785.     { hugemulmod(result,result,reg1);
  786.       if(kbhit()) if(getch()=='e') return;
  787.       if(reg1byte>>15) { hugemul(result,num,FALSE);
  788.              hugerdiv(result,reg1,FALSE);
  789.                }
  790.       reg1byte<<=1;
  791.     }
  792.   }
  793.   if((result[0]==1)&&(result[1]==num)) printf("Pseudoprime\n\r");
  794.   else printf("Composite\n\r");
  795. }
  796.  
  797. /*
  798.    heres pollards method of factorisation
  799.    use after removing small factors
  800.    factors produced will have to be tested for primeness
  801.    can give some good results
  802. */
  803.  
  804. void pollard(unsigned int *reg1,unsigned int num)
  805. { unsigned int test[2*MAXLEN+1],
  806.            wk1[2*MAXLEN+1],
  807.            loops;
  808.   int mulcount;
  809.   long count=3;
  810.   char ch;
  811.   bool gcdtest=TRUE;
  812.   test[0]=test[1]=1;
  813.   for(mulcount=0;mulcount<32;mulcount++)
  814.     hugemul(test,num,TRUE);
  815.   hugedec(test);
  816.   do
  817.   { if(gcdtest)
  818.     { hugeequ(wk1,reg1);
  819.       hugegcd(wk1,test);
  820.       if(!((wk1[0]==1)&&(wk1[1]==1)))
  821.       { printf("Factor : ");
  822.     hugepri(wk1,FALSE);
  823.     hugerdiv(reg1,wk1,TRUE);
  824.     return;
  825.       }
  826.     }
  827.     if(kbhit()){ ch=getch();
  828.          if(ch=='e') return;
  829.          else if(ch=='o'){ if(gcdtest){ gcdtest=FALSE;
  830.                         printf("gcd test off\n\r");
  831.                           }
  832.                    else { gcdtest=TRUE;
  833.                       printf("gcd test on\n\r");
  834.                     }
  835.                  }
  836.          else printf("%lu\n\r",count);
  837.            }
  838.     wk1[0]=wk1[1]=1;
  839.     hugeinc(test,FALSE);
  840.     loops=31;
  841.     while(!(count&(1<<loops)))loops--;
  842.     for(mulcount=loops;mulcount>=0;mulcount--)
  843.     { hugemulmod(wk1,wk1,reg1);
  844.       if(count&(1<<mulcount)) hugemulmod(wk1,test,reg1);
  845.     }
  846.     hugeequ(test,wk1);
  847.     hugedec(test);
  848.     if(count>1000)
  849.       do count+=2;
  850.       while((!(count%3))||(!(count%5))||(!(count%7))||(!(count%11))||(!(count%13)));
  851.     else if(count>100)count+=2;
  852.     else count++;
  853.   } while(count!=1);
  854.   printf("No factor found\n\r");
  855. }
  856.  
  857. /*
  858.    performs psp test multiple times over primes<num
  859. */
  860.  
  861. void autopsptest(unsigned int *reg1,unsigned int num)
  862. { unsigned int count=0;
  863.   while((num>=primes[count])&&(primes[count]))
  864.   { printf("%u - ",primes[count]);
  865.     psptest(reg1,primes[count++]);
  866.   }
  867. }
  868.  
  869. /*
  870.    a montecarlo method of factorisation
  871.    crap it is too. any better ?
  872. */
  873.  
  874. void montecarlo(unsigned int *reg1,unsigned int num)
  875. { unsigned int test[2*MAXLEN+1],
  876.            count,
  877.            wk1[2*MAXLEN+1];
  878.   test[0]=count=1;
  879.   test[1]=num;
  880.   do
  881.   { hugeequ(wk1,reg1);
  882.     hugegcd(wk1,test);
  883.     if (!((wk1[0]==1)&&(wk1[1]==1))){ printf("Factor : ");
  884.                       hugepri(wk1,FALSE);
  885.                       hugerdiv(reg1,wk1,TRUE);
  886.                       return;
  887.                     }
  888.     if(kbhit())if(getch()=='e')return;
  889.            else printf("%u\n\r",count);
  890.     hugemulmod(test,test,reg1);
  891.     hugeinc(test,TRUE);
  892.     randomize();
  893.     if(random(2)) hugeaddnum(test,random(50),TRUE);
  894.     count++;
  895.   } while(TRUE);
  896. }
  897.  
  898. /*
  899.    the sequence method of factorisation or pollards rho method
  900.    could take some optimisation - see a text on advanced number
  901.    theory, or Riesels book on computer methods of factorisation
  902.    still works quite well but don't wait too long
  903. */
  904.  
  905. void sequence(unsigned int *reg1,unsigned int num)
  906. { unsigned int testu[2*MAXLEN+1],
  907.            testv[2*MAXLEN+1],
  908.            wk1[2*MAXLEN+1],
  909.            count=1;
  910.   testu[0]=testv[0]=1;
  911.   testu[1]=testv[1]=num;
  912.   do
  913.   { hugemulmod(testu,testu,reg1);
  914.     hugemulmod(testv,testv,reg1);
  915.     hugeinc(testu,TRUE);
  916.     hugeinc(testv,TRUE);
  917.     hugemulmod(testv,testv,reg1);
  918.     hugeinc(testv,TRUE);
  919.     hugeequ(wk1,testu);
  920.     hugeadd(wk1,reg1,FALSE);
  921.     hugersub(wk1,testv);
  922.     hugegcd(wk1,reg1);
  923.     if(!((wk1[0]==1)&&(wk1[1]==1))){ printf("Factor : ");
  924.                      hugepri(wk1,FALSE);
  925.                      hugerdiv(reg1,wk1,TRUE);
  926.                      return;
  927.                    }
  928.     if(kbhit())if(getch()=='e')return;
  929.            else printf("%u\n\r",count);
  930.     count++;
  931.   } while(TRUE);
  932. }
  933.  
  934. /*
  935.    heres an interesting one. This calculates num^reg1 mod reg2
  936. */
  937.  
  938. void powmod(unsigned int num,unsigned int *reg1,unsigned int *reg2)
  939. { unsigned int result[2*MAXLEN+1],
  940.            len1,
  941.            reg1byte,
  942.            bytecount;
  943.   result[0]=result[1]=1;
  944.   len1=reg1[0];
  945.   while(len1)
  946.   { reg1byte=reg1[len1--];
  947.     for (bytecount=0;bytecount<16;bytecount++)
  948.     { hugemulmod(result,result,reg2);
  949.       if(reg1byte>>15){ hugemul(result,num,FALSE);
  950.             hugerdiv(result,reg2,FALSE);
  951.               }
  952.       reg1byte<<=1;
  953.     }
  954.   }
  955.   hugeequ(reg1,result);
  956. }
  957.  
  958. /*
  959.    witness was a bad phrase to use but these routines are used in
  960.    PROVING a number to be prime. See doc for details
  961. */
  962.  
  963. bool witnesstest(unsigned int *reg1,unsigned int *reg2,unsigned int num)
  964. { unsigned int power[2*MAXLEN+1];
  965.   hugeequ(power,reg1);
  966.   hugedec(power);
  967.   hugerdiv(power,reg2,TRUE);
  968.   powmod(num,power,reg1);
  969.   if(!((power[0]==1)&&(power[1]==1)))return TRUE;
  970.   return FALSE;
  971. }
  972.  
  973. void witness(unsigned int *reg1,unsigned int *reg2,unsigned int num)
  974. { if(witnesstest(reg1,reg2,num))printf("Passed\n\r");
  975.   else printf("Failed\n\r");
  976. }
  977.  
  978. void findwitness(unsigned int *reg1,unsigned int *reg2)
  979. { unsigned int i=0;
  980.   do
  981.   { if(witnesstest(reg1,reg2,primes[i]))
  982.     { printf("Witness %u - checking pseudoprime\n\r",primes[i]);
  983.       psptest(reg1,primes[i]);
  984.       return;
  985.     }
  986.   } while(primes[++i]);
  987.   printf("No witness found\n\r");
  988. }
  989.  
  990. /*
  991.    this routine will do most of the work for you
  992.    it only stops if n-1 cannot immediately be factorised
  993.    for a large number
  994. */
  995.  
  996. void proveprime(unsigned int *reg1,unsigned int *reg2)
  997. { unsigned int trial=2,
  998.            count=0,
  999.            carry,
  1000.            test[2*MAXLEN+1],
  1001.            psps[256],
  1002.            i;
  1003.   bool table=TRUE,
  1004.        done;
  1005.   hugeequ(reg2,reg1);
  1006.   hugedec(reg2);
  1007.   for(i=0;i<256;i++)psps[i]=0;
  1008.   do
  1009.   { hugemod(reg2,trial,&carry);
  1010.     if(!carry)
  1011.     { while(!carry)
  1012.       { hugediv(reg2,trial,&carry);
  1013.     hugemod(reg2,trial,&carry);
  1014.       }
  1015.       test[0]=1;
  1016.       test[1]=trial;
  1017.       printf("Factor : %u looking for witness\n\r",trial);
  1018.       i=0;
  1019.       done=FALSE;
  1020.       do
  1021.       { if(witnesstest(reg1,test,primes[i]))
  1022.     { printf("Witness : %u checking pseudoprime\n\r",primes[i]);
  1023.       if(psps[primes[i]]) printf("Pseudoprime\n\r");
  1024.       else
  1025.       { hugeequ(test,reg1);
  1026.         hugedec(test);
  1027.         powmod(primes[i],test,reg1);
  1028.         if((test[0]==1)&&(test[1]==1))
  1029.         { printf("Pseudoprime\n\r");
  1030.           psps[primes[i]]=1;
  1031.         }
  1032.         else
  1033.         { printf("N is composite\n\r");
  1034.           return;
  1035.         }
  1036.       }
  1037.       done=TRUE;
  1038.     }
  1039.       } while((primes[++i])&&(!done));
  1040.       if(!done)
  1041.       { printf("No witness found\n\r");
  1042.     return;
  1043.       }
  1044.     }
  1045.     if(table) trial=primes[++count];
  1046.     if(!trial)
  1047.     { table=FALSE;
  1048.       trial=primes[count-1];
  1049.     }
  1050.     if(!table)
  1051.     { do
  1052.       { count=0;
  1053.     done=TRUE;
  1054.     trial+=2;
  1055.     do
  1056.     { if(!(trial%primes[count])) done=FALSE;
  1057.     } while(primes[++count]);
  1058.       } while(!done);
  1059.     }
  1060.   } while(trial!=1);
  1061.   if(reg2[0]==2)
  1062.   { printf("Factor : ");
  1063.     hugepri(reg2,TRUE);
  1064.     printf(" looking for witness\n\r");
  1065.     hugeequ(test,reg2);
  1066.     i=0;
  1067.     done=FALSE;
  1068.     do
  1069.     { if(witnesstest(reg1,test,primes[i]))
  1070.       { printf("Witness : %u checking pseudoprime\n\r",primes[i]);
  1071.     if(psps[primes[i]]) printf("Pseudoprime\n\r");
  1072.     else
  1073.     { hugeequ(test,reg1);
  1074.       hugedec(test);
  1075.       powmod(primes[i],test,reg1);
  1076.       if((test[0]==1)&&(test[1]==1))
  1077.       { printf("Pseudoprime\n\r");
  1078.         psps[primes[i]]=1;
  1079.       }
  1080.       else
  1081.       { printf("N is composite\n\r");
  1082.         return;
  1083.       }
  1084.     }
  1085.     done=TRUE;
  1086.       }
  1087.     } while((primes[++i])&&(!done));
  1088.     if(!done){ printf("No witness found\n\r");
  1089.            return;
  1090.          }
  1091.     reg2[0]=reg2[1]=1;
  1092.   }
  1093.   if((reg2[0]==1)&&(reg2[1]==1)) printf("N is prime\n\r");
  1094.   else
  1095.   { hugeequ(test,reg1);
  1096.     hugedec(test);
  1097.     hugerdiv(test,reg2,TRUE);
  1098.     hugemul(test,256,FALSE);
  1099.     hugemul(test,256,FALSE);
  1100.     hugermul(test,test,FALSE);
  1101.     done=FALSE;
  1102.     if(test[0]>reg1[0])done=TRUE;
  1103.     else if(test[0]==reg1[0])
  1104.      { i=test[0];
  1105.        while((i)&&(!done))
  1106.        { if(test[i]>reg1[i]) done=TRUE;
  1107.          else if(test[i]==reg1[i])i=1;
  1108.          i--;
  1109.        }
  1110.      }
  1111.     if(!done){ printf("Test unfinished - residue left to be checked\n\r");
  1112.            return;
  1113.          }
  1114.     printf("Residue : ");
  1115.     hugepri(reg2,TRUE);
  1116.     printf(" looking for witness\n\r");
  1117.     hugeequ(test,reg2);
  1118.     i=0;
  1119.     done=FALSE;
  1120.     do
  1121.     { if(witnesstest(reg1,test,primes[i]))
  1122.       { printf("Witness : %u checking pseudoprime\n\r",primes[i]);
  1123.     if(psps[primes[i]]) printf("Pseudoprime\n\r");
  1124.     else
  1125.     { hugeequ(test,reg1);
  1126.       hugedec(test);
  1127.       powmod(primes[i],test,reg1);
  1128.       if((test[0]==1)&&(test[1]==1))
  1129.       { printf("Pseudoprime\n\r");
  1130.         psps[primes[i]]=1;
  1131.       }
  1132.       else
  1133.       { printf("N is composite\n\r");
  1134.         return;
  1135.       }
  1136.     }
  1137.     done=TRUE;
  1138.       }
  1139.     } while((primes[++i])&&(!done));
  1140.     if(!done){ printf("Test unfinished - residue left to be checked\n\r");
  1141.            return;
  1142.          }
  1143.     reg2[0]=reg2[1]=1;
  1144.     printf("N is prime\n\r");
  1145.   }
  1146. }
  1147.  
  1148. /*
  1149.    calculates factorial
  1150. */
  1151.  
  1152. void factorial(unsigned int *reg1,unsigned int num)
  1153. { reg1[0]=0;
  1154.   hugeinc(reg1,FALSE);
  1155.   while(num>1) hugemul(reg1,num--,TRUE);
  1156. }
  1157.  
  1158. /*
  1159.    calculates 2^reg1
  1160. */
  1161.  
  1162. void power2(unsigned int *reg1,unsigned int num)
  1163. { reg1[0]=0;
  1164.   hugeinc(reg1,FALSE);
  1165.   while(num--) hugemul2(reg1,TRUE);
  1166. }
  1167.  
  1168. /*
  1169.    and this does num^reg1
  1170. */
  1171.  
  1172. void pown(unsigned int *reg1,unsigned int num)
  1173. { unsigned int test[2*MAXLEN+1];
  1174.   test[0]=test[1]=1;
  1175.   while(num--) hugermul(test,reg1,TRUE);
  1176.   hugeequ(reg1,test);
  1177. }
  1178.  
  1179. /*
  1180.    heres the old favourite fermats method of factorisation
  1181.    a sieve is employed for speed with 20 values defined at the start
  1182.    of the program.
  1183.    Still seems a bit slow though or am I expecting too much
  1184. */
  1185. void fermatsieve(unsigned int *reg1)
  1186. { int i,
  1187.       j,
  1188.       calc;
  1189.   bool done,
  1190.        show;
  1191.   unsigned int wk1[2*MAXLEN+1],
  1192.            wk2[2*MAXLEN+1],
  1193.            wk3[2*MAXLEN+1],
  1194.            carry;
  1195.   for(i=0;i<NUM_SIEVEVALUES;i++)
  1196.     for(j=0;j<sievevalue[i];j++)
  1197.       sieves[(i<<8)+j]=0;
  1198.   for(i=0;i<NUM_SIEVEVALUES;i++)
  1199.     for(j=0;j<sievevalue[i];j++)
  1200.     { calc=(j*j)%(sievevalue[i]);
  1201.       sieves[(i<<8)+calc]|=256;
  1202.     }
  1203.   for(i=0;i<NUM_SIEVEVALUES;i++)
  1204.   { hugemod(reg1,sievevalue[i],&carry);
  1205.     for(j=0;j<sievevalue[i];j++)
  1206.     { calc=(j*j-carry+sievevalue[i])%(sievevalue[i]);
  1207.       if(sieves[(i<<8)+calc]&256)sieves[(i<<8)+j]|=1;
  1208.     }
  1209.   }
  1210.   for(i=0;i<NUM_SIEVEVALUES;i++)
  1211.     for(j=0;j<sievevalue[i];j++)
  1212.       sieves[(i<<8)+j]&=1;
  1213.   hugeroot(wk1,reg1);
  1214.   hugeinc(wk1,FALSE);
  1215.   for(i=0;i<NUM_SIEVEVALUES;i++)
  1216.     hugemod(wk1,sievevalue[i],&modtable[i]);
  1217.   show=FALSE;
  1218.   for(;;)
  1219.   { done=FALSE;
  1220.     i=0;
  1221.     do
  1222.     { if(!(sieves[(i<<8)+modtable[i]])) done=TRUE;
  1223.     } while((++i<NUM_SIEVEVALUES)&&(!done));
  1224.     if(kbhit())if(getch()=='e')return;
  1225.            else show=TRUE;
  1226.     if(!done)
  1227.     { hugeequ(wk2,wk1);
  1228.       hugermul(wk2,wk2,FALSE);
  1229.       hugersub(wk2,reg1);
  1230.       hugeroot(wk3,wk2);
  1231.       hugeequ(wk2,wk1);
  1232.       hugersub(wk2,wk3);
  1233.       if(show){ hugepri(wk2,FALSE);
  1234.         show=FALSE;
  1235.           }
  1236.       hugegcd(wk2,reg1);
  1237.       if(!((wk2[0]==1)&&(wk2[1]==1)))
  1238.       { printf("Factor : ");
  1239.     hugepri(wk2,FALSE);
  1240.     hugerdiv(reg1,wk2,TRUE);
  1241.     return;
  1242.       }
  1243.     }
  1244.     hugeinc(wk1,FALSE);
  1245.     for(i=0;i<NUM_SIEVEVALUES;i++)
  1246.       if((++modtable[i])==sievevalue[i]) modtable[i]=0;
  1247.   }
  1248. }
  1249.  
  1250. /*
  1251.    heres the command interpreter
  1252.    pretty basic , nuff said
  1253. */
  1254. bool command(void)
  1255. { bool cquit=FALSE;
  1256.   int incount=0;
  1257.   int bufptr=0;
  1258.   int comptr=0;
  1259.   unsigned int *regptr,*regptr2;
  1260.   unsigned int tempreg[MAXLEN+1];
  1261.   char ch;
  1262.   char buffer[MAXLEN+30];
  1263.   textcolor(CYAN);
  1264.   cprintf("Command>");
  1265.   textcolor(LIGHTGRAY);
  1266.   _setcursortype(_NORMALCURSOR);
  1267.   while(!cquit)
  1268.   { ch=getch();
  1269.     if(ch==13){ cquit=TRUE;
  1270.         buffer[incount]=0;
  1271.         printf("\n\r");
  1272.           }
  1273.     else if((ch==8)&&(incount>0)){ incount--;
  1274.                    printf("%c %c",ch,ch);
  1275.                  }
  1276.     else if((incount<MAXLEN+29)&&(ch>31)&&(ch<127)){ buffer[incount++]=ch;
  1277.                              printf("%c",ch);
  1278.                            }
  1279.   }
  1280.   _setcursortype(_NOCURSOR);
  1281.   strlwr(buffer);
  1282.   cquit=FALSE;
  1283.   while(buffer[bufptr]==' ') bufptr++;
  1284.   do
  1285.   { if(!strncmp(comtable[comptr].cmd,&buffer[bufptr],strlen(comtable[comptr].cmd)))
  1286.       cquit=TRUE;
  1287.     if(!cquit) comptr++;
  1288.   } while((!cquit)&&(comtable[comptr].cmd!=NULL));
  1289.   if(!cquit) { printf("Unknown Command\n\r");
  1290.            return(TRUE);
  1291.          }
  1292.   else if(comtable[comptr].arg1==QUIT) return(FALSE);
  1293.   bufptr+=strlen(comtable[comptr].cmd);
  1294.   while(buffer[bufptr]==' ') bufptr++;
  1295.   switch(comtable[comptr].arg1)
  1296.   { case REG: switch(buffer[bufptr])
  1297.           { case 'a': regptr=regA;
  1298.               bufptr++;
  1299.               break;
  1300.         case 'b': regptr=regB;
  1301.               bufptr++;
  1302.               break;
  1303.         case 'c': regptr=regC;
  1304.               bufptr++;
  1305.               break;
  1306.         case 'd': regptr=regD;
  1307.               bufptr++;
  1308.               break;
  1309.         default : printf("Unknown Register\n\r");
  1310.               return(TRUE);
  1311.           }
  1312.           break;
  1313.     case NIL: regptr=NULL;
  1314.           break;
  1315.     default:  printf("Program Error\n\r");
  1316.           exit(1);
  1317.   }
  1318.   while((buffer[bufptr]==',')||(buffer[bufptr]==' ')) bufptr++;
  1319.   regptr2=NULL;
  1320.   switch(comtable[comptr].arg2)
  1321.   { case CVALUE: switch(buffer[bufptr])
  1322.          { case 'a': regptr2=regA;
  1323.                  bufptr++;
  1324.                  break;
  1325.            case 'b': regptr2=regB;
  1326.                  bufptr++;
  1327.                  break;
  1328.            case 'c': regptr2=regC;
  1329.                  bufptr++;
  1330.                  break;
  1331.            case 'd': regptr2=regD;
  1332.                  bufptr++;
  1333.                  break;
  1334.            default : regptr2=tempreg;
  1335.                  incount=0;
  1336.                  if(!buffer[bufptr]){ printf("Too few arguments\n\r");
  1337.                           return(TRUE);
  1338.                         }
  1339.                  while((buffer[bufptr]>='0')&&(buffer[bufptr]<='9'))
  1340.                    buffer[incount++]=buffer[bufptr++];
  1341.                  buffer[incount]=0;
  1342.                  hugeinp(tempreg,buffer);
  1343.          }
  1344.          while(buffer[bufptr]==' ')bufptr++;
  1345.          if(buffer[bufptr]){ printf("Too many arguments\n\r");
  1346.                      return(TRUE);
  1347.                    }
  1348.          if(comtable[comptr].arg3==NIL)
  1349.            (*comtable[comptr].fn)(regptr,regptr2);
  1350.          else if(comtable[comptr].arg3==TVAL)
  1351.            (*comtable[comptr].fn)(regptr,regptr2,TRUE);
  1352.          else if(comtable[comptr].arg3==FVAL)
  1353.            (*comtable[comptr].fn)(regptr,regptr2,FALSE);
  1354.          else { printf("Program Error\n\r");
  1355.             exit(1);
  1356.               }
  1357.          break;
  1358.     case NUM   : incount=0;
  1359.          if(!buffer[bufptr]){ printf("Too few arguments\n\r");
  1360.                       return(TRUE);
  1361.                     }
  1362.          while((buffer[bufptr]>='0')&&(buffer[bufptr]<='9'))
  1363.          { incount=incount*10+buffer[bufptr]-'0';
  1364.            bufptr++;
  1365.          }
  1366.          while(buffer[bufptr]==' ') bufptr++;
  1367.          if(buffer[bufptr]){ printf("Too many arguments\n\r");
  1368.                      return(TRUE);
  1369.                    }
  1370.          if(comtable[comptr].arg3==NIL)
  1371.            (*comtable[comptr].fn)(regptr,incount);
  1372.          else { printf("Program Error\n\r");
  1373.             exit(1);
  1374.               }
  1375.          break;
  1376.     case NIL   : if(comtable[comptr].arg1==NIL)
  1377.            (*comtable[comptr].fn)();
  1378.          else if(comtable[comptr].arg3==NIL)
  1379.            (*comtable[comptr].fn)(regptr);
  1380.          else if(comtable[comptr].arg3==TVAL)
  1381.            (*comtable[comptr].fn)(regptr,TRUE);
  1382.          else if(comtable[comptr].arg3==FVAL)
  1383.            (*comtable[comptr].fn)(regptr,FALSE);
  1384.          else { printf("Program Error\n\r");
  1385.             exit(1);
  1386.               }
  1387.          break;
  1388.     default    : printf("Program Error\n\r");
  1389.          exit(1);
  1390.   }
  1391.   return(TRUE);
  1392. }
  1393.  
  1394. /*
  1395.    main routine
  1396.    doesn't do a lot just loops
  1397. */
  1398.  
  1399. int main(void)
  1400. { init();
  1401.   clrscr();
  1402.   textcolor(RED);
  1403.   cprintf("Multi-Precision Integer Maths Program v1.0\n\r");
  1404.   cprintf("By Paul Young\n\r");
  1405.   cprintf("Public Domain\n\r\n\r");
  1406.   textcolor(LIGHTGRAY);
  1407.   do
  1408.   {} while (command());
  1409.   _setcursortype(_NORMALCURSOR);
  1410.   return(0);
  1411. }
  1412.